/*
 * Copyright (C) 2008,2009,2010,2011  Paulo Cesar Pereira de Andrade.
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Authors:
 *	Paulo Cesar Pereira de Andrade
 */

#ifndef _etag_h
#define _etag_h

#include "etypes.h"

#define type_declare		0
#define type_define		1
#define type_prototype		2
#define type_function		3
#define type_method_prototype	4
#define type_method_function	5

#define etag_p(object)		(etype(object) == t_tag)

typedef enum etag_type {
    tag_void,

    /* order is tag_basic, tag_struct, tag_class, tag_union */
    tag_basic,
    tag_struct,
    tag_class,
    tag_union,

    tag_vector,
    tag_pointer,
    tag_function,
    tag_hashtable
} etag_type_t;

struct etag {
    etag_t	*next;
    esymbol_t	*name;
    eobject_t	 data;
    eint32_t	 key;
    etag_type_t	 type;
};

/*
 * Prototypes
 */
extern etag_t *
etag_object(eobject_t object);

/* this function modifies the argument list changing union field access
 * from the format:
 *	(field expr name)
 *   to
 *	(type expr #<tag>)
 */
extern etag_t *
etag_expression(eobject_t list);

extern etag_t *
etag_vector(etag_t *base, eobject_t list);

extern etag_t *
etag_function(etag_t *type, eobject_t list);

extern etag_t *
etag_pointer(etag_t *base);

extern etag_t *
etag_opaque(etype_t type, etag_type_t tag_type);

/* returns false if argument matches ellipsis ('...')
 * ident_r is set to null if no symbol name is available */
extern ebool_t
eargument(eobject_t list, etag_t **type_r, eobject_t *ident_r);

extern eint32_t
etypename(etag_t *tag, eint32_t state, eobject_t form, eobject_t spec,
	  etag_t **type_r, eobject_t *ident_r, eobject_t *spec_r,
	  ebool_t deftype);

extern void
echeck_void(eobject_t list);

extern ebool_t
eliteral_p(eobject_t object);

extern ebool_t
etag_number_p(etag_t *tag);

extern eint_t
etag_to_integer(etag_t *tag);

extern char *
erecord_token_string(etoken_t token);

extern etype_t
etag_packed_p(etag_t *tag);

extern void
init_tag(void);

/*
 * Externs
 */
extern eobject_t ellipsis_obj;
extern eobject_t function_obj;
extern eobject_t this_obj;
extern etag_t *void_tag;
extern etag_t *char_tag;
extern etag_t *int_tag;
extern etag_t *float_tag;
extern etag_t *function_tag;
extern etag_t *vararg_tag;
extern etag_t *string_tag;
extern etag_t *pointer_tag;
extern etag_t *hashtable_tag;

#endif /* _etag_h */
